package cn.golxen.blog.rabbitMQ.consumer;

import cn.golxen.blog.commons.rabbitVo.*;
import cn.golxen.blog.commons.utils.RabbitMQTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.*;
import cn.golxen.blog.entity.Essay;
import cn.golxen.blog.mapper.EssayMapper;

import com.alibaba.fastjson.JSON;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

@Slf4j
@Component
public class EssayConsumer {

    @Autowired
    EssayMapper essayMapper;
    @Autowired
    RedisTemplate<String,String> redisTemplate;

    @RabbitListener(queues = "EssayQue")
    @RabbitHandler
    public void essayHandler(RabbitMQTemplate rabbitMQTemplate){
//        System.out.println("中");
        if(rabbitMQTemplate!=null)
        switch (rabbitMQTemplate.getType()){
            case "addRedisEssayList":
                addRedisEssayList((AddRedisEssayListVo) rabbitMQTemplate);
                break;
            case "deleteRedisEssay":
                deleteEssay((DeleteRedisEssayVo) rabbitMQTemplate);
                break;
            case "addRedisEssay":
                addRedisEssay((AddRedisEssayVo) rabbitMQTemplate);
                break;
            case "updateMySqlViews":
                UpdateMySqlViews((UpdateMySqlViewsVo) rabbitMQTemplate);
                break;
            case "addRedisCountOfCategory":
                addRedisCountOfCategory((AddRedisCountOfCategoryVo)rabbitMQTemplate);
                break;
            case "deleteRedisEssayByCategoryAndLabel":
                deleteRedisEssayByCategoryAndLabel((DeleteRedisEssayByCategoryAndLabelVo)rabbitMQTemplate);
                break;
            case "addRedisEssayByCategory":
                addRedisEssayByCategory((AddRedisEssayByCategoryVo)rabbitMQTemplate);
                break;
            case "addRedisEssayByLabel":
                addRedisEssayByLabel((AddRedisEssayByLabelVo)rabbitMQTemplate);
                break;
            case "addRedisLabelByEssay":
                addRedisLabelByEssay((AddRedisLabelByEssayVo)rabbitMQTemplate);
                break;
            case "deleteRedisLabelByEssay":
                deleteRedisLabelByEssay((DeleteRedisLabelByEssayVo)rabbitMQTemplate);
        }
    }

    private void deleteRedisLabelByEssay(DeleteRedisLabelByEssayVo rabbitMQTemplate) {
        Set<String> keys=new HashSet<>();
        rabbitMQTemplate.getEssayId().forEach((value)->{
            keys.add("essay:"+value+":label_set");
        });
        redisTemplate.delete(keys);
    }

    private void addRedisLabelByEssay(AddRedisLabelByEssayVo rabbitMQTemplate) {
        RedisSerializer<String> serializer=redisTemplate.getStringSerializer();
        redisTemplate.executePipelined((RedisCallback<String>) connection->{
            rabbitMQTemplate.getLabelSet().forEach((value)->{
                connection.sAdd(serializer.serialize("essay:"+rabbitMQTemplate.getEssayId()+":label_set"), serializer.serialize(value));
            });
            connection.expire(serializer.serialize("essay:"+rabbitMQTemplate.getEssayId()+":label_set"),3600);
            return null;
        });
    }

    private void addRedisEssayByLabel(AddRedisEssayByLabelVo rabbitMQTemplate) {
        if (rabbitMQTemplate.getEssaySet().isEmpty()){
            redisTemplate.opsForSet().add("label:" + rabbitMQTemplate.getLabel() + ":essay_set", "空");
            redisTemplate.expire("label:" + rabbitMQTemplate.getLabel() + ":essay_set",3600, TimeUnit.SECONDS);
            log.info("empty");
        }
        RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
        redisTemplate.executePipelined((RedisCallback<String>) connection->{
            rabbitMQTemplate.getEssaySet().forEach((value) -> {
                String essayStr=JSON.toJSONString(value);
                connection.sAdd(serializer.serialize("label:"+rabbitMQTemplate.getLabel()+":essay_set"),
                        serializer.serialize(essayStr));

            });
            connection.expire(serializer.serialize("label:"+rabbitMQTemplate.getLabel()+":essay_set"),3600);
            return null;
        });
    }

    private void addRedisEssayByCategory(AddRedisEssayByCategoryVo rabbitMQTemplate) {
        if (rabbitMQTemplate.getSet().isEmpty()){
            redisTemplate.opsForSet().add("category:" + rabbitMQTemplate.getCategory() + ":essay_set", "空");
            redisTemplate.expire("category:" + rabbitMQTemplate.getCategory() + ":essay_set",3600, TimeUnit.SECONDS);
            log.info("empty");
        }
        RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
        redisTemplate.executePipelined((RedisCallback<String>) connection->{
            rabbitMQTemplate.getSet().forEach((value) -> {
                String essayStr=JSON.toJSONString(value);
                connection.sAdd(serializer.serialize("category:"+rabbitMQTemplate.getCategory()+":essay_set"),
                        serializer.serialize(essayStr));

            });
            connection.expire(serializer.serialize("category:"+rabbitMQTemplate.getCategory()+":essay_set"),3600);
            return null;
        });
    }

    private void addRedisEssayList(AddRedisEssayListVo addRedisEssayListVo){
        List<Essay> list= addRedisEssayListVo.getList();
        String page=addRedisEssayListVo.getPage();
        String total= addRedisEssayListVo.getTotal();

//        System.out.println("前");
        RedisSerializer<String> serializer = redisTemplate.getStringSerializer();

        AtomicReference<Float> f= new AtomicReference<>((float) 1);
        redisTemplate.executePipelined((RedisCallback<String>) connection -> {
            list.forEach((value) -> {
                String jsonObject= JSON.toJSONString(value);
                connection.zAdd(Objects.requireNonNull(serializer.serialize("essayList"+page)), f.get(),serializer.serialize(jsonObject));
                f.getAndSet(f.get() + 1);
            });
            connection.expire(Objects.requireNonNull(serializer.serialize("essayList"+page)),3600);
            connection.set(Objects.requireNonNull(serializer.serialize("pagetotal")), Objects.requireNonNull(serializer.serialize(total)));
            connection.expire(Objects.requireNonNull(serializer.serialize("pagetotal")),3600);
            return null;
        });
    }

    private void deleteEssay(DeleteRedisEssayVo deleteRedisEssayVo){
        RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
        Set<String> essayListSet=redisTemplate.keys("essayList*");
        Set<String> keyss = new HashSet<>();
        if (deleteRedisEssayVo.getKeys()!=null){

            Set<String> labelSetKeys=new HashSet<>();
            deleteRedisEssayVo.getKeys().forEach((value)->{
                labelSetKeys.add("essay:"+value+":label_set");
            });
            redisTemplate.delete(labelSetKeys);

            Iterator<String> iterator=deleteRedisEssayVo.getKeys().stream().iterator();
            while (iterator.hasNext()){
                String key="id:"+ iterator.next() +"*";
                Set<String> keys=redisTemplate.keys(key);
                if (keys!=null)
                    keyss.addAll(keys);
            }
        }
        redisTemplate.executePipelined((RedisCallback<String>) connection ->{

            connection.del(serializer.serialize("essay_count"));
            if (essayListSet!=null){
                for (String nextKey : essayListSet) {
                    connection.del(serializer.serialize(nextKey));
                }
            }
            if (!keyss.isEmpty()){
                for (String nextKey : keyss){
                    connection.del(serializer.serialize(nextKey));
                }
            }

            return null;
        });
    }

    private void addRedisEssay(AddRedisEssayVo addRedisEssayVo){

        String key="id:"+addRedisEssayVo.getEssay().getEssayId()+":title:"+addRedisEssayVo.getEssay().getTitle();
        String essay=JSON.toJSONString(addRedisEssayVo.getEssay());
        redisTemplate.opsForValue().set(key,essay,3600, TimeUnit.SECONDS);
    }

    private void UpdateMySqlViews(UpdateMySqlViewsVo updateMySqlViewsVo){
        essayMapper.addViewById(updateMySqlViewsVo.getEssayId(),updateMySqlViewsVo.getViews());
        log.info("执行浏览添加数据库");
    }

    private void addRedisCountOfCategory(AddRedisCountOfCategoryVo addRedisCountOfCategoryVo){
        redisTemplate.opsForValue().set("category:"+addRedisCountOfCategoryVo.getCategory()+":count_essay",addRedisCountOfCategoryVo.getCount(),3600,TimeUnit.SECONDS);
    }

    private void deleteRedisEssayByCategoryAndLabel(DeleteRedisEssayByCategoryAndLabelVo deleteRedisEssayByCategoryAndLabelVo){
        RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
        if (deleteRedisEssayByCategoryAndLabelVo.getCategory()!=null){
            redisTemplate.delete("category:"+ deleteRedisEssayByCategoryAndLabelVo.getCategory()+":count_essay");
            redisTemplate.delete("category:"+ deleteRedisEssayByCategoryAndLabelVo.getCategory()+":essay_set");
        }else{
            Set<String> countSet=redisTemplate.keys("category:*:count_essay");
            Set<String> essaySet=redisTemplate.keys("category:*:essay_set");

            if (countSet!=null){
                redisTemplate.executePipelined((RedisCallback<String>) connection->{
                    for (String key:countSet
                         ) {
                        connection.del(serializer.serialize(key));
                    }
                return null;
            });}

            if (essaySet!=null){
                redisTemplate.executePipelined((RedisCallback<String>) connection->{
                    for (String key:essaySet
                    ) {
                        connection.del(serializer.serialize(key));
                    }
                    return null;
                });}

        }

        Set<String> essaySet=redisTemplate.keys("label:*:essay_set");
        if (essaySet!=null){
            log.info("有去删label:*:essay_set");
            redisTemplate.executePipelined((RedisCallback<String>) connection->{
                for (String key:essaySet
                ) {
                    connection.del(serializer.serialize(key));
                }
                return null;
            });}

    }

}
